﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using System.Runtime.InteropServices;
using DevExpress.LookAndFeel;
using DevExpress.Utils.Drawing;
using DevExpress.Skins.XtraForm;
using DevExpress.Skins;

namespace ProgNetComponentsDx.Forms
{
    public partial class HideToTrayForm : XtraForm 
    {
        private FormWindowState LastWindowState;

        public event EventHandler HidenToTray;
        public event EventHandler ShownFromTray;
        public event CancelEventHandler HidingToTray;
        public event CancelEventHandler ShowingFromTray;

        private bool StateSet = false;
        [DefaultValue(true)]
        public bool AutoHideNotifyIcon
        {
            get;
            set;
        }
        
        [DefaultValue(ToogleHideType.SingleClick)]
        public ToogleHideType ToogleHideType
        {
            get;
            set;
        }
       
        public HideToTrayForm():base()
        {
            InitializeComponent();
            AutoHideNotifyIcon = true;
            if (notifyIcon1.Icon == null)
                notifyIcon1.Icon = this.Icon;
            ToogleHideType = Forms.ToogleHideType.SingleClick;
        }

        protected override DevExpress.Skins.XtraForm.FormPainter CreateFormBorderPainter()
        {
           return new MyFormPainter(this);
        }

        protected override object GetSkinPainterType()
        {
            return typeof(MyFormPainter);
        }
        
        public virtual void HideToTray()
        {
            if (HidingToTray != null)
            {
                CancelEventArgs e = new CancelEventArgs();
                HidingToTray(this, e);
                if (e.Cancel)
                    return;
            }
            LastWindowState = WindowState;
            StateSet = true;
            this.Hide();
            notifyIcon1.Visible = true;
            

            if (HidenToTray != null)
                HidenToTray(this, EventArgs.Empty);
        }
        public virtual void ShowFromTray()
        {
            if (ShowingFromTray != null)
            {
                CancelEventArgs e = new CancelEventArgs();
                ShowingFromTray(this, e);
                if (e.Cancel)
                    return;
            }
            this.Show();
            try
            {
                User32.SetForegroundWindow(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);
                User32.SetActiveWindow(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);
            }
            catch { }
            if (StateSet)
                this.WindowState = LastWindowState;
            if (this.AutoHideNotifyIcon)
                notifyIcon1.Visible = false;
            else
                notifyIcon1.Visible = true;
            if (ShownFromTray != null)
                ShownFromTray(this, EventArgs.Empty);
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (ToogleHideType == Forms.ToogleHideType.DoubleClick)
                {
                    if (Visible)
                        HideToTray();
                    else
                        ShowFromTray();
                }
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (!this.IsDesignMode())
            {
                if (notifyIcon1.Text.IsNullOrEmpty())
                    notifyIcon1.Text = Application.ProductName;

                if (AutoHideNotifyIcon)
                {
                    notifyIcon1.Visible = !this.Visible;
                }
                else
                {
                    notifyIcon1.Visible = true;
                }
            }
        }

        private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (ToogleHideType == Forms.ToogleHideType.SingleClick)
                {
                    if (Visible)
                        HideToTray();
                    else
                        ShowFromTray();
                }
            }
        }
    }
    public enum ToogleHideType
    {
        None,
        SingleClick,
        DoubleClick
    }
    public class MyFormPainter : DevExpress.Skins.XtraForm.FormPainter
    {
        public MyFormPainter(HideToTrayForm form)
            : base(form, form.LookAndFeel)
        {
            this.SetFieldValue("buttonPainter", new MyFormCaptionButtonSkinPainter(this));
            hideToTrayForm = form;
        }
        private HideToTrayForm hideToTrayForm;

        internal DevExpress.Skins.XtraForm.FormCaptionButton MinToTrayBtn
        {
            get { return minToTrayBtn; }
        }
        DevExpress.Skins.XtraForm.FormCaptionButton minToTrayBtn = null;

        protected override void CheckReady()
        {
            if (!IsReady)
            {
                if (this.Provider == null)
                {
                    this.SetFieldValue("provider", (Owner as XtraForm).LookAndFeel);
                }
                base.CheckReady();
                int left = 0;
                int top = 0;
                int w = 19;
                int h = 19;
                DevExpress.Skins.XtraForm.FormCaptionButton btn = null;
                if (this.ShouldAddMaximizeButton(Owner as Form) && (Owner as Form).MinimizeBox &&
                    this.ShouldAddMinimizeButton(Owner as Form) && (Owner as Form).MaximizeBox)
                {
                    btn = Buttons[DevExpress.Skins.XtraForm.FormCaptionButtonKind.Minimize];
                }
                else
                {
                    btn = Buttons[DevExpress.Skins.XtraForm.FormCaptionButtonKind.Close];
                }

                if (btn != null)
                {
                    left = btn.Bounds.Left - w;
                    top = btn.Bounds.Top;
                }
                if (minToTrayBtn == null)
                    minToTrayBtn = new DevExpress.Skins.XtraForm.FormCaptionButton(DevExpress.Skins.XtraForm.FormCaptionButtonKind.All);
                
                Buttons.Add(minToTrayBtn);

                minToTrayBtn.Bounds = new Rectangle(left, top, w, h);
            }
        }

        protected override void OnClick(MouseEventArgs e, DevExpress.Skins.XtraForm.FormCaptionButtonAction kind)
        {
            if (Buttons.GetButton(e, this) == minToTrayBtn)
            {
                if (Owner.Visible)
                    (this.Owner as HideToTrayForm).HideToTray();
                else
                    (this.Owner as HideToTrayForm).ShowFromTray();
                return;
            }

            base.OnClick(e, kind);
        }

        protected override DevExpress.Utils.Drawing.ObjectState CalcButtonState(DevExpress.Skins.XtraForm.FormCaptionButton button)
        {
            ObjectState objectState = ObjectState.Normal;
            objectState = base.CalcButtonState(button);
            if (button == minToTrayBtn)
            {
                Point p =  this.PointToFormBounds(Control.MousePosition);
                if (Buttons.GetButton(p) == minToTrayBtn)
                {
                    objectState |= ObjectState.Hot;
                    if (button.Kind == this.PressedButton)
                        objectState |= ObjectState.Pressed;
                }
                else
                {
                    objectState = ObjectState.Normal;
                }
                return objectState;
            }
            else
            {
                return base.CalcButtonState(button);
            }
        }
    }

    public class MyFormCaptionButtonSkinPainter : FormCaptionButtonSkinPainter
    {
        MyFormPainter Painter;
        public MyFormCaptionButtonSkinPainter(MyFormPainter painter)
            : base(painter.Provider)
        {
            Painter = painter;
        }

        protected override DevExpress.Skins.SkinElement GetSkinElement(ObjectInfoArgs e)
        {

            if (e == Painter.MinToTrayBtn)
            {
                return DevExpress.Skins.FormSkins.GetSkin(Provider)[DevExpress.Skins.FormSkins.SkinFormButtonMdiMinimize];
            }
            else
            {
                DevExpress.Skins.SkinElement el = base.GetSkinElement(e);
                return el;
            }
        }
    }

}
